home *** CD-ROM | disk | FTP | other *** search
/ PD Collection CD 1 / PD Collection CD 1.iso / textual / pdimpres / !PD-Impres / c / PD-Impres < prev   
Text File  |  1990-08-25  |  18KB  |  450 lines

  1. /* -> c.PD-Impres */
  2.  
  3. /*
  4.  * Desktop utility to convert PipeDream documents into text files suitable for Impression, while still retaining style and
  5.  * formatting information where possible. The utility lives on the icon bar, converting any PipeDream (type DDE) dropped there).
  6.  * ie This program converts PipeDream documents into DDF format text
  7.  *
  8.  * © Stuart Hickinbottom 31mar90
  9.  */
  10.  
  11. /* #define TRACE TRUE */ /* Comment out this macro definition to produce a production version of the code */
  12.  
  13. /* Include the various headers I require... */
  14. #include "wimp.h"
  15. #include "wimpt.h"
  16. #include "win.h"
  17. #include "event.h"
  18. #include "baricon.h"
  19. #include "res.h"
  20. #include "resspr.h"
  21. #include "menu.h"
  22. #include "template.h"
  23. #include "dbox.h"
  24. #include "werr.h"
  25. #include "xferrecv.h"
  26. #include "trace.h"
  27. #include "visdelay.h"
  28. #include "saveas.h"
  29. #include "flex.h"
  30. #include "bbc.h"
  31.  
  32. #include <string.h>
  33. #include <stdlib.h>
  34.  
  35. /* Define any constants which I require... */
  36. #define PDImpress_menu_info     1 /* Menu items */
  37. #define PDImpress_menu_quit     2
  38. #define PDImpress_info_field    4 /* Info box icon number for the version string */
  39. #define PDImpress_loadtype      0xdde
  40. #define PDImpress_savetype      0xfff
  41. #define Special_character       '%'   /* The special character that indicates a command */
  42. #define Max_highlight_size      50   /* The maximum length of a PipeDream highlight code, I think this is column definition */
  43. #define Buffer_increase 512     /* Define the amount by which the buffer is incremented. Should be >= max DDF line length */
  44. #define RAM_xfername "DDF_File" /* Define the name to be used in the export box if RAM xfer used */
  45.  
  46. /* Define any constant static data which I need... */
  47. static char *pdimpress_Version_String = "0.13 (31 March 1990)"; /* Application version text */
  48. static menu pdimpress_menu;                                     /* The top of the menu tree */
  49. static char in_file_name[255];         /* Hold the file name of the PipeDream file   */
  50. static char *in_file = in_file_name;   /* Point to this memory                       */
  51. static char *pd_text = NULL;           /* Pointer to loaded PipeDream text in memory */
  52. static char *ddf_text = NULL;          /* Pointer to DDF format converted text       */
  53. static int  ddf_size;                  /* The size of the DDF text buffer. Increases */
  54. static int  pd_file_size;              /* The size of the PipeDream document         */
  55. static int  offset_ddf;                /* The offset into the DDF text buffer        */
  56. static int  offset_pd;                 /* The offset into the PD text buffer         */
  57.  
  58. /*
  59.  * This table defines the translation from PipeDream highlight codes to Impression DDF commands. For each highlight code
  60.  * there is the PipeDream command name and then the Impression style name. There is then a flag which this code uses to
  61.  * remember whether the style is currently on or off. This table may be freely expanded.
  62.  */
  63.  
  64. static char *highlight_trans[][] =
  65.             {
  66.             {"H1", "Underline",     "Off"}, /* Style:   Underline         */
  67.             {"H2", "Bold",          "Off"}, /* Style:   Bold              */
  68.             {"H3", "Main Heading",  "Off"}, /* Style:   Extended sequence */
  69.             {"H4", "Italic",        "Off"}, /* Style:   Italic            */
  70.             {"H5", "Subscript",     "Off"}, /* Style:   Subscript         */
  71.             {"H6", "Superscript",   "Off"}, /* Style:   Superscript       */
  72.             {"H7", "Typewriter",    "Off"}, /* Style:   Alternative font  */
  73.             {"H8", "Sub-heading",   "Off"}, /* Style:   User defined      */
  74.             {"JL", "Fully Justify", "Off"}, /* Style:   Justified         */
  75.             {"JR", "Fully Justify", "Off"}, /* Style:   Justified         */
  76.             {"C",  "Centre",        "Off"}, /* Justify: Centre            */
  77.             {"**", "",              ""   }  /* Terminating value          */
  78.             };
  79.  
  80. static char *highlight_ignore[] = /* Define highlight codes which cause the 'interpreter' to skip the line */
  81.             {
  82.             "OP",                 /* Ignore page description lines   */
  83.             "**",                 /* Terminating value               */
  84.             };
  85.  
  86. /* Table of special highlights which are converted directly into text, for example the percentage symbol */
  87. static char *highlight_text[][] =
  88.             {
  89.             {"PC", "%"      },        /* Convert PC into the percentage symbol */
  90.             {"**", ""       }         /* Terminating value                     */
  91.             };
  92.  
  93. /* Any highlight code which is not in any of the above tables is simply skipped over - no action is taken */
  94.  
  95. /* Main program polling loop */
  96. int main()
  97. {
  98.  BOOL pdimpress_initialise(void);
  99.  if (pdimpress_initialise())
  100.   {
  101.   while (TRUE) /* The main event loop */
  102.    event_process();
  103.   }
  104.  return 0; /* Return, as there was a problem which prevented successful initialisation */
  105. }
  106.  
  107. /* Event handler called on a left click on the icon */
  108. void pdimpress_iconclick(wimp_i icon)
  109. {
  110.  void pdimpress_info_about_program(void);
  111.  icon = icon;                    /* We don't need the handle: this stops compiler warning */
  112.  pdimpress_info_about_program(); /* Just display 'About this program' window */
  113. }
  114.  
  115. /* Display the program info box - called from the menu processor */
  116. void pdimpress_info_about_program(void)
  117. {
  118.  dbox  d;  /* Dialogue box handle */
  119.  if (d = dbox_new("progInfo"), d != NULL) /* Create the dialogue box */
  120.   {
  121.   dbox_setfield(d, PDImpress_info_field, pdimpress_Version_String); /* Fill in the version number */
  122.   dbox_show(d); /* Show the dialogue box */
  123.   dbox_fillin(d); /* Keep it on the screen as long as needed */
  124.   dbox_dispose(&d); /* Dispose of the dialogue box */
  125.   }
  126. }
  127.  
  128. /* Event handler for the menu */
  129. void pdimpress_menuproc(void *handle, char *hit)
  130. {
  131.  handle = handle; /* We don't need handle: this stops compiler warning */
  132.  switch (hit[0]) /* Find which menu item was hit and take action as appropriate */
  133.   {
  134.   case PDImpress_menu_info:
  135.        pdimpress_info_about_program();
  136.        break;
  137.   case PDImpress_menu_quit:
  138.        exit(0); /* Exit from the program. The wimp gets rid of the window and icon */
  139.   }
  140. }
  141.  
  142. /* Event handler for icon bar events */
  143. BOOL pdimpress_bar_event_handler(wimp_eventstr *e, void *handle)
  144. {
  145.  void load_ram(void), load_file(void);
  146.  handle = handle; /* We don't need handle: this stops compiler warning */
  147.  switch (e->e) /* Deal with event */
  148.   {
  149.   case wimp_ESEND:
  150.   case wimp_ESENDWANTACK:
  151.        switch (e->data.msg.hdr.action)
  152.         {
  153.         case wimp_MDATASAVE:
  154.              load_ram();
  155.              return(TRUE);
  156.         case wimp_MDATALOAD:
  157.         case wimp_MDATAOPEN:
  158.              load_file();
  159.              return(TRUE);
  160.         }
  161.   default:   /* Ignore any other event */
  162.   return(FALSE);
  163.   }
  164. }
  165.  
  166. /* Load the file, utilising direct RAM data transfer from another application */
  167. void load_ram(void)
  168. {
  169.  BOOL buffer_processor(char **, int *);
  170.  void load_file(void), convert_pd_file(int), do_ddf_save(void), clean_up(void);
  171.  int estimated_size, actual_size, file_type, alloc_success;
  172.  file_type = xferrecv_checkimport(&estimated_size);
  173.  if (file_type != -1) /* If we really can load via RAM then... */
  174.   {
  175.   if (file_type == PDImpress_loadtype)
  176.    {
  177.    pd_file_size = 0;
  178.    if ((alloc_success = flex_alloc((flex_ptr) &pd_text, estimated_size)) == NULL)
  179.     werr(FALSE,"There is not enough memory to load the PipeDream document - try to free some using the Task Manager");
  180.    else
  181.     {
  182.     visdelay_begin();
  183.     in_file = RAM_xfername; /* Make up a name, as there isn't one supplied on RAM xfer */
  184.     tracef1("estimated RAM xfer size is %d bytes\n", estimated_size);
  185.     actual_size = xferrecv_doimport(pd_text, estimated_size, buffer_processor);
  186.     tracef1("xfer was %d bytes\n", pd_file_size);
  187.     if (actual_size >= 0) /* If the xfer was successful then... */
  188.      {
  189.      convert_pd_file(pd_file_size);
  190.      visdelay_end();
  191.      if (ddf_size != 0) do_ddf_save();
  192.      clean_up();
  193.      }
  194.     else /* There was an error during the xfer */
  195.      {
  196.      flex_free((flex_ptr) &pd_text);
  197.      visdelay_end();
  198.      /* Sender got scared during the RAM xfer? The sending application should try by file instead... */
  199.      }
  200.     }
  201.    }
  202.   }
  203.  else
  204.   {
  205.    load_file();
  206.   }
  207. }
  208.  
  209. /* Handle the RAM buffer becomming full during the RAM xfer */
  210. BOOL buffer_processor(char **buffer, int *size)
  211. {
  212.  int success_flag;
  213.  pd_file_size += *size; /* Record number of bytes xfer'd so far */
  214.  tracef0("buffer processor called\n");
  215.  success_flag = flex_extend((flex_ptr) &pd_text, pd_file_size + Buffer_increase);
  216.  if (success_flag == 0)
  217.   {
  218.   tracef0("Not enough memory during buffer_processor\n");
  219.   return(FALSE); /* If buffer increase failed, then return error */
  220.   }
  221.  *buffer += *size; /* Advance the buffer pointer into the new area */
  222.  *size    = Buffer_increase; /* Size to xfer is this new areas size */
  223.  return TRUE; /* Continue the xfer */
  224. }
  225.  
  226. /* Handle a file icon being dropped onto me. If it is acceptable then load it */
  227. void load_file(void)
  228. {
  229.  char *filename;
  230.  void convert_pd_file(int), do_ddf_save(void), clean_up(void);
  231.  int read_pd_file(void);
  232.  int filetype = xferrecv_checkinsert(&filename);
  233.  strcpy(in_file, filename);
  234.  tracef1("load_file, filetype %x\n", filetype);
  235.  if (filetype == PDImpress_loadtype)
  236.   {
  237.   visdelay_begin();
  238.   tracef0("loading file....\n");
  239.   pd_file_size = read_pd_file();
  240.   if (pd_file_size != 0) convert_pd_file(pd_file_size);
  241.   xferrecv_insertfileok();
  242.   visdelay_end();
  243.   if ((pd_file_size != 0) && (ddf_size != 0)) do_ddf_save(); /* Do save if dragged to something that wants the DDF text file */
  244.   clean_up(); /* Dispose of PipeDream and DDF documents from the flex area */
  245.   }
  246. }
  247.  
  248. /* Initialise the program, returning TRUE if it was all OK */
  249. BOOL pdimpress_initialise(void)
  250. {
  251.  /* RISC_OSlib initialisation of the various modules I use */
  252.  wimpt_init("PD -> Impression");  /* Main Wimp initialisation */
  253.  res_init("PD-Impres");           /* Resources */
  254.  resspr_init();                   /* Application sprites */
  255.  template_init();                 /* Templates */
  256.  dbox_init();                     /* Dialogue boxes */
  257.  visdelay_init();                 /* Hourglass */
  258.  flex_init();                     /* Flex */
  259.  if (pdimpress_menu = menu_new("PD-Impres", ">Info,Quit"), pdimpress_menu == NULL) /* Create the menu tree */
  260.   return FALSE; /* Menu create failed */
  261.  win_add_unknown_event_processor(pdimpress_bar_event_handler, 0); /* Grab unknown events for my icon (files dropped etc.) */
  262.  baricon("!PD-Impres", (int)resspr_area(), pdimpress_iconclick); /* Set up the icon on the bar, and declare its event handlers */
  263.  if (!event_attachmenu(win_ICONBAR, pdimpress_menu, pdimpress_menuproc, 0))
  264.   return FALSE; /* Unable to attach menu */
  265.  trace_on(); /* Turn tracing on. This will only occur if the macro TRACE was defined at the start, though */
  266.  return TRUE; /* All went ok, so indicate this */
  267. }
  268.  
  269. /* Read in the PipeDream file, allocating enough space to hold the entire file in one go */
  270. int read_pd_file(void)
  271. {
  272.  FILE *pd_file_handle;
  273.  int pd_file_size, alloc_success;
  274.  tracef0("opening file");
  275.  if ((pd_file_handle = fopen(in_file, "r")) == NULL)
  276.   {
  277.   werr(FALSE, "Strange, the PipeDream file could not be opened (not found?)");
  278.   return(0); /* Return a length of 0 - not loaded */
  279.   }
  280.  fseek(pd_file_handle, 0,2);
  281.  pd_file_size = (int)ftell(pd_file_handle);
  282.  fseek(pd_file_handle, 0,0);
  283.  tracef1(", file size is %d bytes\n", pd_file_size);
  284.  if ((alloc_success = flex_alloc((flex_ptr) &pd_text, pd_file_size)) == NULL)
  285.   {
  286.   werr(FALSE,"There is not enough memory to load the PipeDream document - try to free some using the Task Manager");
  287.   fclose(pd_file_handle);
  288.   return(0);
  289.   }
  290.  tracef0("reading text from file\n");
  291.  fread(pd_text, 1, pd_file_size, pd_file_handle);
  292.  tracef0("closing file\n");
  293.  fclose(pd_file_handle);
  294.  return(pd_file_size);
  295. }
  296.  
  297. /* Write out the DDF format version of the text to a file */
  298. BOOL write_ddf_file(char *out_file, void *handle)
  299. {
  300.  os_filestr file;
  301.  BOOL ok;
  302.  handle = handle; /* Stop compiler warning */
  303.  file.action   = 0x0a;                    /* Save block and date stamp file */
  304.  file.name     = out_file;
  305.  file.loadaddr = PDImpress_savetype;      /* File type */
  306.  file.start    = (int)ddf_text;
  307.  file.end      = (int)(ddf_text + offset_ddf);
  308.  ok = (wimpt_complain(os_file(&file)) == 0);
  309.  tracef1("written %d bytes\n", (int)offset_ddf);
  310.  return(ok);
  311. }
  312.  
  313. /* Clean up at the end of the conversion, or if an error has occured - ie free memory etc. */
  314. void clean_up(void)
  315. {
  316.  if (pd_text != 0)  flex_free((flex_ptr) &pd_text);
  317.  if (ddf_text != 0) flex_free((flex_ptr) &ddf_text);
  318. }
  319.  
  320. /* Convert the PipeDream file into a DDF format file - this is the biggie!! */
  321. void convert_pd_file(int pd_file_size)
  322. {
  323.  void handle_embedded(void), all_highlights_off(void), ensure_highlights_off(void), increase_buffer(void);
  324.  int success_flag;
  325.  tracef1("converting text (%d bytes source), ", pd_file_size);
  326.  offset_pd = 0;
  327.  offset_ddf = 0;
  328.  ddf_size = Buffer_increase;
  329.  success_flag = flex_alloc((flex_ptr) &ddf_text, Buffer_increase);
  330.  if (success_flag == 0)
  331.   {
  332.   werr(FALSE, "There is not enough memory to convert the PipeDream document - try to free some using the Task Manager");
  333.   flex_free((flex_ptr) &ddf_text);
  334.   ddf_size = 0;
  335.   }
  336.  all_highlights_off();
  337.  while ((offset_pd < pd_file_size) && (ddf_size != 0))
  338.   {
  339.   while (pd_text[offset_pd] == Special_character) handle_embedded();
  340.   if ((pd_text[offset_pd] == '\x0a') || (pd_text[offset_pd] == '\x0d')) ensure_highlights_off();
  341.   if (offset_pd < pd_file_size) ddf_text[offset_ddf++] = pd_text[offset_pd];
  342.   offset_pd++;
  343.   if ((ddf_size - offset_ddf) < Buffer_increase)
  344.    increase_buffer();
  345.   }
  346.   tracef0("done\n");
  347. }
  348.  
  349. /* Handle an embedded command, converting it into DDF */
  350. void handle_embedded(void)
  351. {
  352.  char character, *highlight;
  353.  int highlight_size, highlight_number, strcmp(char *, char *);
  354.  void toggle_highlight_on(int), insert_ddf(int);
  355.  flex_alloc((flex_ptr) &highlight, Max_highlight_size);
  356.  highlight_size = 0;
  357.  while ((character = pd_text[++offset_pd]) != Special_character) highlight[highlight_size++] = character; /* Read command */
  358.  offset_pd++;
  359.  highlight[highlight_size] = NULL;
  360.  highlight_number = 0;
  361.  while ((strcmp(highlight_ignore[highlight_number], "**") != 0) && strcmp(highlight_ignore[highlight_number], highlight) != 0)
  362.   highlight_number++; /* Check if this command is to be ignored */
  363.  if (strcmp(highlight_ignore[highlight_number], "**") != 0) /* If this command should be ignored then... */
  364.   while ((pd_text[offset_pd] != '\x0a') && (pd_text[offset_pd++] != '\x0d')); /* Skip the rest of this line */
  365.  else
  366.   {
  367.   highlight_number = 0;
  368.   while ((strcmp(highlight_trans[highlight_number][0], "**") != 0) && strcmp(highlight_trans[highlight_number][0], highlight) != 0)
  369.    highlight_number++; /* Check if this command is to be translated to a DDF command */
  370.   if (strcmp(highlight_trans[highlight_number][0], "**") != 0) /* If this command should be translated then... */
  371.    {
  372.    toggle_highlight_on(highlight_number);
  373.    insert_ddf(highlight_number);
  374.    }
  375.   else
  376.    {
  377.    highlight_number = 0;
  378.    while ((strcmp(highlight_text[highlight_number][0], "**") != 0) && strcmp(highlight_text[highlight_number][0], highlight) != 0)
  379.     highlight_number++; /* Check if this command is to be translated to a text alternative */
  380.    if (strcmp(highlight_text[highlight_number][0], "**") != 0) /* If this command should be translated then... */
  381.     offset_ddf += sprintf(&(ddf_text[offset_ddf]), "%s", highlight_text[highlight_number][1]); /* Copy in the translated string */
  382.    }
  383.   }
  384.  flex_free((flex_ptr) &highlight);
  385. }
  386.  
  387. /* Increase the buffer for the DDF text by the amount defined by Buffer_increase */
  388. void increase_buffer(void)
  389. {
  390.  int success_flag;
  391.  success_flag = flex_extend((flex_ptr) &ddf_text, ddf_size + Buffer_increase);
  392.  if (success_flag == 0)
  393.   {
  394.   werr(FALSE, "Insufficent memory to convert PipeDream document - try to free some using the Task Manager");
  395.   flex_free((flex_ptr) &ddf_text);
  396.   ddf_size = 0;
  397.   }
  398.  else
  399.   ddf_size += Buffer_increase;
  400. }
  401.  
  402. /* Toggle my flag which indicates whether a highlight is currently turn on. Used to turn all off at end of a line */
  403. void toggle_highlight_on(int highlight_number)
  404. {
  405.  if (highlight_trans[highlight_number][2] == "Off")
  406.   highlight_trans[highlight_number][2] = "On";
  407.  else
  408.   highlight_trans[highlight_number][2] = "Off";
  409. }
  410.  
  411. /* This inserts the DDF equivalent of the highlight code, using the 'on flag' to decide whether to turn it on or off */
  412. void insert_ddf(int highlight_number)
  413. {
  414.  offset_ddf += sprintf(&(ddf_text[offset_ddf]), "{\"%s\" %s}",
  415.   highlight_trans[highlight_number][1], highlight_trans[highlight_number][2]);
  416. }
  417.  
  418. /* Reset all the highlights to be initially off */
  419. void all_highlights_off(void)
  420. {
  421.  int highlight_number, strcmp(char *, char *);
  422.  highlight_number = 0;
  423.  while (strcmp(highlight_trans[highlight_number][0], "**") != 0)
  424.   highlight_trans[highlight_number++][2] = "Off";
  425. }
  426.  
  427. /* Ensure that all highlights are off at the end of a line, by issuing 'off' DDF commands to turn highlights off */
  428. void ensure_highlights_off(void)
  429. {
  430.  int highlight_number, strcmp(char*, char*);
  431.  void toggle_highlight_on(int), insert_ddf(int);
  432.  highlight_number = 0;
  433.  while (strcmp(highlight_trans[highlight_number][0], "**") != 0)
  434.   {
  435.   if (highlight_trans[highlight_number][2] == "On")
  436.    {
  437.    toggle_highlight_on(highlight_number);
  438.    insert_ddf(highlight_number);
  439.    }
  440.   highlight_number++;
  441.   }
  442. }
  443.  
  444. /* Allow the user to export the DDF file, by dragging from the save dialogue box */
  445. void do_ddf_save(void)
  446. {
  447.  BOOL write_ddf_file(char *, void *);
  448.  saveas(PDImpress_savetype, in_file, offset_ddf, write_ddf_file, 0 /* No RAM xfer */, 0 /* No printer xfer */, 0);
  449. }
  450.